{
  // 联合类型

  //
  let u: string | number;
  u = "xxx";
  u = 12411;
  u = NaN;

  // 类型断言 建议使用方式一
  // 方式一： 值 as 类型
  // let div = document.querySelector("div") as HTMLDivElement;
  // div.style.background = "#cea";

  //方式二：<类型>值
  // let div = document.querySelector('div');
  // (<HTMLDivElement>div).style.background = '#cea';

  // 类型断言的用法
  // 用法一：将一个联合类型断言为其中一个类型
  interface Cat {
    name: string;
    run(): void;
  }
  interface Fish {
    name: string;
    swim(): void;
  }

  function getName(animal: Cat | Fish): string {
    return animal.name;
  }

  function isFish(animal: Cat | Fish): boolean {
    // 断言为联合类型中的 Fish
    if (typeof (animal as Fish).swim === "function") {
      return true;
    }
    return false;
  }

  function swim(animal: Cat | Fish) {
    (animal as Fish).swim();
  }

  const tom: Cat = {
    name: "Tom",
    run() {
      console.log("run");
    },
  };
  // 类型断言只能够「欺骗」TypeScript 编译器
  // 编译时不报错，无法避免运行时报错
  swim(tom);
  // Uncaught TypeError: animal.swim is not a function`

  // 用法二：将一个父类断言为更加具体的子类
  class ApiError extends Error {
    code: number = 0;
  }
  class HttpError extends Error {
    statusCode: number = 0;
  }

  function isApiError(error: Error) {
    if (typeof (error as ApiError).code === "number") {
      return true;
    }
    return false;
  }

  // 用法三： 将任何一个类型断言为 any
  let obj: object = {};
  // obj.a = 100;
  // error TS2339: Property 'a' does not exist on type 'object'.

  // 在 any 类型的变量上，访问任何属性都是允许的。
  (obj as any).a = 1;
}
